import fetch from 'node-fetch';

interface StockListResponse {
  rc: number; // 返回码
  rt: number;
  svr: number;
  lt: number;
  full: number;
  dlmkts: string;
  data: {
    total: number; // 总股票数量
    diff: StockData[];
  };
}

interface StockData {
  f1: number;   // 类型标识
  f2: number;   // 最新价
  f3: number;   // 涨跌幅
  f4: number;   // 涨跌额
  f5: number;   // 成交量
  f6: number;   // 成交额
  f7: number;   // 振幅
  f8: number;   // 换手率
  f9: number;   // 市盈率
  f10: number;  // 量比
  f11: number;  // 五分钟涨跌
  f12: string;  // 股票代码
  f13: number;  // 市场标识 (0=深市, 1=沪市)
  f14: string;  // 股票名称
  f15: number;  // 最高价
  f16: number;  // 最低价
  f17: number;  // 今开
  f18: number;  // 昨收
  f19: number;  // 权限标识
  f20: number;  // 总市值
  f21: number;  // 流通市值
  f22: number;  // 涨跌
  f23: number;  // 市净率
  f24: number;  // 本周涨跌幅
  f25: number;  // 本月涨跌幅
}

interface ParsedStockData {
  stockCode: string;
  stockName: string;
  marketCode: string;
  sector: string;
  currentPrice: number;
  openPrice: number;
  highPrice: number;
  lowPrice: number;
  closePrice: number;
  changeAmount: number;
  changePercent: number;
  volume: bigint;
  turnover: number;
  marketCap: number;
  peRatio?: number;
  pbRatio?: number;
}

export class EastMoneyAPI {
  private baseURL = 'http://82.push2.eastmoney.com/api/qt/clist/get';
  private maxRetries = 3;
  private retryDelay = 1000;
  private requestDelay = 500;

  constructor(config?: {
    maxRetries?: number;
    retryDelay?: number;
    requestDelay?: number;
  }) {
    if (config) {
      this.maxRetries = config.maxRetries || this.maxRetries;
      this.retryDelay = config.retryDelay || this.retryDelay;
      this.requestDelay = config.requestDelay || this.requestDelay;
    }
  }

  /**
   * 获取所有A股列表数据
   * @param page 页码，从1开始
   * @param pageSize 每页数量，默认20，API最大返回100
   * @returns 解析后的股票数据数组
   */
  async getAllAStockList(page: number = 1, pageSize: number = 100): Promise<{
    stocks: ParsedStockData[];
    total: number;
    currentPage: number;
    totalPages: number;
  } | null> {
    const params = {
      cb: 'jQuery', // JSONP回调
      pn: page.toString(), // 页码
      pz: pageSize.toString(), // 每页数量
      po: '1', // 正序
      np: '1', // 不分页？
      ut: 'bd1d9ddb04089700cf9c27f6f7426281', // 固定参数
      fltt: '2', // 过滤参数
      invt: '2', // 类型参数
      fid: 'f3', // 排序字段 (f3=涨跌幅)
      fs: 'm:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23' // 市场过滤: 深A+创业板+沪A+科创板
    };

    const url = `${this.baseURL}?${new URLSearchParams(params).toString()}`;
    
    console.log(`正在获取A股列表数据: 第${page}页，每页${pageSize}条`);

    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        await this.delay(this.requestDelay);

        const response = await fetch(url, {
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Referer': 'http://quote.eastmoney.com/'
          }
        });

        if (!response.ok) {
          throw new Error(`HTTP Error: ${response.status}`);
        }

        const text = await response.text();
        
        // 解析JSONP响应
        const jsonMatch = text.match(/jQuery\((.+)\);?$/);
        if (!jsonMatch) {
          throw new Error('无法解析JSONP响应');
        }

        const data: StockListResponse = JSON.parse(jsonMatch[1]);
        
        if (data.rc !== 0) {
          throw new Error(`API返回错误: ${data.rc}`);
        }

        if (!data.data || !data.data.diff) {
          throw new Error('API返回数据格式错误');
        }

        // 解析股票数据
        const stocks = data.data.diff.map(this.parseStockData).filter(Boolean) as ParsedStockData[];
        
        const totalPages = Math.ceil(data.data.total / pageSize);
        
        console.log(`✅ 成功获取第${page}页数据，共${stocks.length}只股票，总计${data.data.total}只`);
        
        return {
          stocks,
          total: data.data.total,
          currentPage: page,
          totalPages
        };

      } catch (error: any) {
        console.error(`获取A股列表失败 (尝试 ${attempt}/${this.maxRetries})`, error.message);
        
        if (attempt === this.maxRetries) {
          return null;
        }
        
        await this.delay(this.retryDelay * attempt);
      }
    }
    
    return null;
  }

  /**
   * 获取完整的A股股票列表（所有页面）
   * @param maxPages 最大页数，防止无限循环，默认60页（约6000只股票）
   * @returns 所有股票数据
   */
  async getAllAStocks(maxPages: number = 60): Promise<ParsedStockData[]> {
    const allStocks: ParsedStockData[] = [];
    let currentPage = 1;
    const pageSize = 100; // API限制每页最多100只
    
    console.log(`开始获取完整A股列表，最大页数: ${maxPages}`);
    
    while (currentPage <= maxPages) {
      const result = await this.getAllAStockList(currentPage, pageSize);
      
      if (!result) {
        console.error(`获取第${currentPage}页失败，停止获取`);
        break;
      }
      
      allStocks.push(...result.stocks);
      
      // 如果当前页是最后一页，退出循环
      if (currentPage >= result.totalPages) {
        console.log(`✅ 已获取所有页面数据，共${allStocks.length}只股票`);
        break;
      }
      
      currentPage++;
      
      // 页面间延迟，避免请求过频繁
      await this.delay(this.requestDelay * 2);
    }
    
    return allStocks;
  }

  /**
   * 根据股票代码获取实时数据
   * @param stockCodes 股票代码数组
   * @returns 股票实时数据
   */
  async getStockRealtime(stockCodes: string[]): Promise<ParsedStockData[]> {
    if (stockCodes.length === 0) return [];
    
    // 构造股票代码字符串，格式: 0.000001,1.600000
    const formattedCodes = stockCodes.map(code => {
      // 判断市场: 60开头为沪市(1), 00/30开头为深市(0), 688为科创板(1), 300为创业板(0)
      const marketId = code.startsWith('60') || code.startsWith('688') ? '1' : '0';
      return `${marketId}.${code}`;
    }).join(',');

    const params = {
      cb: 'jQuery',
      ut: 'bd1d9ddb04089700cf9c27f6f7426281',
      fltt: '2',
      invt: '2',
      fields: 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23',
      secids: formattedCodes
    };

    const url = `${this.baseURL}?${new URLSearchParams(params).toString()}`;
    
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        await this.delay(this.requestDelay);

        const response = await fetch(url, {
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Referer': 'http://quote.eastmoney.com/'
          }
        });

        if (!response.ok) {
          throw new Error(`HTTP Error: ${response.status}`);
        }

        const text = await response.text();
        const jsonMatch = text.match(/jQuery\((.+)\);?$/);
        if (!jsonMatch) {
          throw new Error('无法解析JSONP响应');
        }

        const data: StockListResponse = JSON.parse(jsonMatch[1]);
        
        if (data.rc !== 0 || !data.data?.diff) {
          throw new Error(`API返回错误或数据为空`);
        }

        return data.data.diff.map(this.parseStockData).filter(Boolean) as ParsedStockData[];

      } catch (error: any) {
        console.error(`获取股票实时数据失败 (尝试 ${attempt}/${this.maxRetries})`, error.message);
        
        if (attempt === this.maxRetries) {
          return [];
        }
        
        await this.delay(this.retryDelay * attempt);
      }
    }
    
    return [];
  }

  /**
   * 解析股票数据
   */
  private parseStockData = (data: StockData): ParsedStockData | null => {
    try {
      if (!data.f12 || !data.f14) {
        return null; // 缺少基本信息
      }

      // 确定市场代码 - 支持更细分的分类
      let marketCode: string;
      let sector: string;
      
      if (data.f13 === 1) {
        // 沪市
        if (data.f12.startsWith('688')) {
          marketCode = 'SH';
          sector = '科创板';
        } else if (data.f12.startsWith('600') || data.f12.startsWith('601') || 
                   data.f12.startsWith('603') || data.f12.startsWith('605')) {
          marketCode = 'SH';
          sector = '沪A主板';
        } else {
          marketCode = 'SH';
          sector = '沪市其他';
        }
      } else {
        // 深市
        if (data.f12.startsWith('300')) {
          marketCode = 'SZ';
          sector = '创业板';
        } else if (data.f12.startsWith('000') || data.f12.startsWith('001')) {
          marketCode = 'SZ';
          sector = '深A主板';
        } else if (data.f12.startsWith('002')) {
          marketCode = 'SZ';
          sector = '中小板';
        } else {
          marketCode = 'SZ';
          sector = '深市其他';
        }
      }

      return {
        stockCode: data.f12,
        stockName: data.f14,
        marketCode,
        sector,
        currentPrice: data.f2 || 0,
        openPrice: data.f17 || 0,
        highPrice: data.f15 || 0,
        lowPrice: data.f16 || 0,
        closePrice: data.f18 || 0,
        changeAmount: data.f4 || 0,
        changePercent: data.f3 || 0,
        volume: BigInt(Math.floor(Number(data.f5) || 0)),
        turnover: data.f6 || 0,
        marketCap: data.f20 || 0,
        peRatio: data.f9 > 0 ? data.f9 : undefined,
        pbRatio: data.f23 > 0 ? data.f23 : undefined
      };
    } catch (error) {
      console.error('解析股票数据失败:', error);
      return null;
    }
  };

  /**
   * 测试API连接性
   */
  async testConnection(): Promise<boolean> {
    try {
      const result = await this.getAllAStockList(1, 1);
      return !!result;
    } catch (error) {
      console.error('测试连接失败:', error);
      return false;
    }
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}